﻿namespace FFXIRC_CLIENT
{
    using System;
    using System.Collections;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;
    using System.Threading;
    using System.Text.RegularExpressions;
    class IRC_to_FFXI
    {
        private Thread reader;
        private Thread writer;

        public static Queue i2fmessageQueue;

        public IRC_to_FFXI()
        {
            i2fmessageQueue = Queue.Synchronized(new Queue());
            reader = new Thread(new ThreadStart(this.readFromIRC));
            writer = new Thread(new ThreadStart(this.writeToFFXI));
        }

        public void Start()
        {
            reader.Start();
            writer.Start();
        }

        public void readFromIRC()
        {
            bool loop = true;
            String inputLine;
            while (loop)
            {
                //loop = FFXI.FFACE.Main.FFXiIsOpen();
                if (IrcClient.myClient.IsConnected == false)
                {
                    Program.isConnectedToIRC.WaitOne();
                }
                inputLine = FFXIRC_CLIENT.IrcClient.myClient.ReadLine(true);
                String[] inputs = inputLine.Split();

                if (inputs.Length < 3)
                    continue;
                //System.Console.Out.WriteLine(inputLine);

                foreach (LineParse lp in IrcClient.f2i.IRC_PARSES)
                {
                    Match LineMatch = lp.Regex.Match(inputLine);
                    if (LineMatch.Success)
                    {
                        IrcClient.f2i.parseCommand(LineMatch.Result(lp.Action).Split(),false);
                    }
                }

                int msg_num = 0;
                try
                {
                    msg_num = int.Parse(inputs[1]);
                }
                catch
                {
                    if (inputs[1] == "PRIVMSG") msg_num = (int)keywordIndex.PRIVMSG;
                    else if (inputs[1] == "JOIN") msg_num = (int)keywordIndex.JOIN;
                    else if (inputs[1] == "NICK") msg_num = (int)keywordIndex.NICK;
                    else if (inputs[1] == "QUIT") msg_num = (int)keywordIndex.QUITIRC;
                    else if (inputs[1] == "PART") msg_num = (int)keywordIndex.PART;
                    else if (inputs[1] == "MODE") msg_num = (int)keywordIndex.MODE;
                    else if (inputs[1] == "TOPIC") msg_num = (int)keywordIndex.TOPIC;
                    else if (inputs[1] == "INVITE") msg_num = (int)keywordIndex.INVITE;
                    else if (inputs[1] == "KICK") msg_num = (int)keywordIndex.KICK;
                    else if (inputs[1] == "NOTICE") msg_num = (int)keywordIndex.NOTICE;
                    else if (inputs[1] == "PING") msg_num = (int)keywordIndex.PONG;
                    else if (inputs[1] == "PONG") msg_num = (int)keywordIndex.PING;
                    else if (inputs[1] == "NAMES") msg_num = (int)keywordIndex.NAMES;
                    else continue;
                }
                String name = "";
                String toSend = "";
                String fromStart = "";
                String from = "";
                String user = "";
                String chan = "";
                String msg = "";
                String setby = "";
                String topic = "";
                switch (msg_num)
                {

                    case (int)keywordIndex.NONE:
                        break;
                    case (int)keywordIndex.PRIVMSG:
                        try
                        {
                            name = inputLine.Substring(inputLine.IndexOf(":") + 1, inputLine.IndexOf("!") - 1);
                        }
                        catch
                        {
                            continue;
                        }
                        fromStart = inputLine.Substring(inputLine.IndexOf("PRIVMSG ") + 8);
                        from = fromStart.Substring(0, fromStart.IndexOf(" "));
                        toSend = "{" + name + "@" + from + "} " + fromStart.Substring(fromStart.IndexOf(":") + 1);
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.NOTICE:

                        name = "";
                        try
                        {
                            name = inputLine.Substring(inputLine.IndexOf(":") + 1, inputLine.IndexOf("!") - 1);
                        }
                        catch
                        {
                            continue;
                        }
                        fromStart = inputLine.Substring(inputLine.IndexOf("NOTICE ") + 7);
                        from = fromStart.Substring(0, fromStart.IndexOf(" "));
                        toSend = "*NOTICE* {" + name + "@" + from + "} " + fromStart.Substring(fromStart.IndexOf(":") + 1);
                        i2fmessageQueue.Enqueue(toSend);
                        break;

                    case 301:
                        // AWAY
                        name = "";
                        try
                        {
                            name = inputs[3];
                        }
                        catch
                        {
                            continue;
                        }
                        fromStart = inputLine.Substring(inputLine.IndexOf("301 ") + 4);
                        from = inputs[2];
                        toSend = "*AWAY* {" + name + "@" + from + "} " + inputLine.Substring(inputLine.IndexOf(inputs[4]) + 1);
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.PING:
                    case (int)keywordIndex.PONG:
                        break;
                    case (int)keywordIndex.JOIN:
                        user = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                        chan = inputs[2].Substring(1);
                        toSend = user + " joined " + chan;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.PART:
                        user = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                        chan = inputs[2];
                        try
                        {
                            msg = inputLine.Substring(inputLine.IndexOf(inputs[2]));
                            msg = msg.Substring(msg.IndexOf(inputs[3]) + 1);
                            if (msg.Length > 1)
                            {
                                toSend = user + " left " + chan + " (" + msg + ")";
                            }
                            else
                            {
                                toSend = user + " left " + chan;
                            }
                        }
                        catch
                        {
                            toSend = user + " left " + chan;
                        }
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.MODE:
                        //mode (+o Tubbers ) by Tubbers2
                        String modes = inputs[3].Replace(":", "");
                        try
                        {
                            from = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                            user = inputs[4];
                            chan = inputs[2];
                            toSend = "{" + chan + "} mode (" + modes + " " + user + ") by " + from;
                            i2fmessageQueue.Enqueue(toSend);
                        }
                        catch
                        {
                            from = inputs[0].Substring(1);
                            chan = inputs[2];
                            toSend = "{" + chan + "} mode (" + modes + ") by " + from;
                            i2fmessageQueue.Enqueue(toSend);
                        }
                        break;

                    case 001: // LARGE FALL THROUGH
                    case 002: //         |
                    case 003: //         |
                    case 004: //         |
                    case 005: //         |
                    case 006: //         |
                    case 250: //         |
                    case 251: //         |
                    case 252: //         |
                    case 254: //         |
                    case 255: //         |
                    case 265: //         |
                    case 266: //         |
                    case 375: //         |
                    case 372: //         V
                    case 376: // FALL THROUGH END
                        toSend = inputLine.Substring(inputLine.IndexOf(inputs[3]) + 1);
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 353:
                        chan = inputs[4];
                        String names = inputLine.Substring(inputLine.IndexOf(inputs[5]));
                        toSend = "{" + chan + "} Users" + names;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 366:
                        chan = inputs[3];
                        toSend = "{" + chan + "} End of /NAMES list.";
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.KICK:
                        //kicked has been kicked by kicker(reason)
                        String kicked = inputs[3];
                        String kicker = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                        String reason = inputLine.Substring(inputLine.IndexOf(inputs[4]) + 1);
                        chan = inputs[2];
                        toSend = "{" + chan + "} " + kicked + " has been kicked by " + kicker + " (" + reason + ")";
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.TOPIC:
                        setby = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                        chan = inputs[2];
                        topic = inputLine.Substring(inputLine.IndexOf(inputs[3]) + 1);
                        toSend = "{" + chan + "} " + setby + " changed the topic to: " + topic;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 332:
                        chan = inputs[3];
                        topic = inputLine.Substring(inputLine.IndexOf(inputs[4]) + 1);
                        toSend = "{" + chan + "} Current Topic: " + topic;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 333:
                        chan = inputs[3];
                        setby = inputLine.Substring(inputLine.IndexOf(inputs[4]));
                        toSend = "{" + chan + "} Topic set by: " + setby;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 391:
                        toSend = "TIME: " + inputLine.Substring(inputLine.IndexOf(inputs[4]) + 1);
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 328:
                        chan = inputs[3];
                        String website = inputLine.Substring(inputLine.IndexOf(inputs[4]) + 1);
                        toSend = "{" + chan + "} Website: " + website;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case 901:
                        name = inputs[2];
                        String message = inputLine.Substring(inputLine.IndexOf(inputs[6]) + 1);
                        toSend = "Welcome " + name + ": " + message;
                        Program.identified.Set();
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    case (int)keywordIndex.NICK:
                        String prevNick = inputs[0].Substring(1, inputs[0].IndexOf("!") - 1);
                        String newNick = inputs[2].Substring(1);
                        toSend = prevNick + " is now known as " + newNick;
                        i2fmessageQueue.Enqueue(toSend);
                        break;
                    default:
                        if (inputLine.Length > 3)
                        {
                            toSend = inputLine;
                            i2fmessageQueue.Enqueue(toSend);
                        }
                        break;
                }
            }
        }

        public void writeToFFXI()
        {
            int max_msg_len = 114;
            while (true)
            {
                DateTime lastSent = DateTime.Now;
                if (i2fmessageQueue.Count > 0)
                {
                    String toSend = (String)i2fmessageQueue.Dequeue();
                    String ircinput = toSend;
                    String prefix = ircinput.Split()[0];
                    bool RTS = true;
                    if (prefix.StartsWith("/"))
                    {
                        try
                        {
                           ircinput = ircinput.Substring(prefix.Length + 1);
                        }
                        catch
                        {
                        }
                        if(prefix == "/l" || prefix == "/p" || prefix == "/s"
                         || prefix == "/sh" || prefix == "/t" || prefix == "/say"
                         || prefix == "/linkshell" || prefix == "/party" || prefix == "shout"
                         || prefix == "/tell")
                        {
                            RTS = false;
                        }
                    }
                    else
                    {
                        prefix = "/echo";
                    }


                    if (ircinput.Length > max_msg_len)
                    {
                        while (ircinput.Length > max_msg_len)
                        {
                            int lastSpace = ircinput.Substring(0, max_msg_len).LastIndexOf(" ");
                            if (lastSpace > 1)
                            {
                                if (!RTS)
                                {
                                    while (DateTime.Now.CompareTo(lastSent.AddMilliseconds(1300)) < 0)
                                    {
                                        Thread.Sleep(10);
                                    }
                                }
                                FFXI.Windower.MainFunctions.SendText(prefix + " " + ircinput.Substring(0, lastSpace));
                                if (!RTS)
                                {
                                    lastSent = DateTime.Now;
                                }
                                ircinput = "*" + ircinput.Substring(lastSpace);
                            }
                            else
                            {
                                if (!RTS)
                                {
                                    while (DateTime.Now.CompareTo(lastSent.AddMilliseconds(1300)) < 0)
                                    {
                                        Thread.Sleep(10);
                                    }
                                }
                                FFXI.Windower.MainFunctions.SendText(prefix + " " + ircinput.Substring(0, max_msg_len));
                                if (!RTS)
                                {
                                    lastSent = DateTime.Now;
                                }
                                ircinput = "* " + ircinput.Substring(max_msg_len);
                            }
                        }
                    }
                    if (ircinput.Length <= max_msg_len)
                    {
                        if (!RTS)
                        {
                            while (DateTime.Now.CompareTo(lastSent.AddMilliseconds(1300)) < 0)
                            {
                                Thread.Sleep(10);
                            }
                        }
                        FFXI.Windower.MainFunctions.SendText(prefix + " " + ircinput);
                        if (!RTS)
                        {
                            lastSent = DateTime.Now;
                        }
                    }


                    /*
                    if (toSend.Length > max_msg_len)
                    {
                        while (toSend.Length > max_msg_len)
                        {
                            
                            if (prefix.StartsWith("/"))
                            {
                                ircinput = ircinput.Substring(prefix.Length + 1);
                            }
                            else
                            {
                                prefix = "";
                            }
                            int lastSpace = toSend.Substring(0, max_msg_len).LastIndexOf(" ");
                            if (lastSpace > 1)
                            {
                                FFXI.Windower.MainFunctions.SendText("/echo " + toSend.Substring(0, lastSpace));
                                toSend = "*" + toSend.Substring(lastSpace);
                            }
                            else
                            {
                                FFXI.Windower.MainFunctions.SendText("/echo " + toSend.Substring(0, max_msg_len));
                                toSend = "* " + toSend.Substring(max_msg_len);
                            }


                        }
                    }
                    if (toSend.Length <= max_msg_len)
                    {
                        FFXI.Windower.MainFunctions.SendText("/echo " + toSend);
                    }*/
                }
                else
                {
                    Thread.Sleep(250);
                }
            }
        }
    }
}
